// 创建时间：2025-06-30
import React, { useRef, useEffect, useState } from 'react';
import { WS_SERVER } from '../config'; // 引入 WebSocket 服务端地址配置
import { VoiceHelper } from '../utils/voiceHelper';

/**
 * AndroidCameraPage 专为安卓浏览器适配，最大兼容安卓 Chrome、Edge、原生浏览器。
 * 兼容标准 getUserMedia 及旧版 webkitGetUserMedia、mozGetUserMedia。
 */
const AndroidCameraPage = () => {
  const videoRef = useRef(null);
  const canvasRef = useRef(null);
  const wsRef = useRef(null);
  const voiceHelper = useRef(new VoiceHelper());
  const [errorMsg, setErrorMsg] = useState('');
  const [debugInfo, setDebugInfo] = useState('');
  const [facingMode, setFacingMode] = useState('user'); // 默认前置
  const streamRef = useRef(null);
  const intervalRef = useRef(null); // 保存定时器id
  const [wsMessage, setWsMessage] = useState(''); // 新增用于显示后端消息
  const [takePhotoFlag, setTakePhotoFlag] = useState(false); // 拍照标志
  // 记录是否已解锁语音
  const voiceUnlocked = useRef(false);
  // 新增：调试信息折叠状态
  const [isDebugExpanded, setIsDebugExpanded] = useState(false);

  // 兼容性封装
  function getUserMediaCompat(constraints) {
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      return navigator.mediaDevices.getUserMedia(constraints);
    }
    const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
    if (getUserMedia) {
      return new Promise((resolve, reject) => {
        getUserMedia.call(navigator, constraints, resolve, reject);
      });
    }
    return Promise.reject(new Error('当前浏览器不支持摄像头调用'));
  }
  

  // 获取所有摄像头设备
  const getCameraDeviceId = async (wantFront = false) => {
    if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) return null;
    try {
      const devices = await navigator.mediaDevices.enumerateDevices();
      const videoInputs = devices.filter(d => d.kind === 'videoinput');
      setDebugInfo(prev => prev + `\n检测到摄像头设备: ` + videoInputs.map(d => `[${d.label || '未知'}] id=${d.deviceId}`).join(' | '));
      if (videoInputs.length === 0) return null;
      // 优先找label含 front/user 的
      if (wantFront) {
        const front = videoInputs.find(d => /front|user/i.test(d.label));
        if (front) return front.deviceId;
        // 没有label时，部分安卓前摄在第一个
        return videoInputs[0].deviceId;
      } else {
        // 优先找label含 back/environment 的
        const back = videoInputs.find(d => /back|environment/i.test(d.label));
        if (back) return back.deviceId;
        // 没有label时，部分安卓后摄在最后一个
        return videoInputs[videoInputs.length - 1].deviceId;
      }
    } catch (e) {
      setDebugInfo(prev => prev + `\nenumerateDevices 错误: ${e.message}`);
      return null;
    }
  };

  // 启动摄像头和推流
  const startCameraAndWS = async (mode = 'user') => {
    setErrorMsg('');
    setDebugInfo(`尝试启动摄像头，模式: ${mode}`);
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
    // 优先用 deviceId
    let constraints = { video: { width: { ideal: 320 }, height: { ideal: 240 } } };
    const wantFront = mode === 'user';
    if (wantFront) {
      constraints.video.facingMode = 'user';
    } else {
      constraints.video.facingMode = 'environment';
    }
    const deviceId = await getCameraDeviceId(wantFront);
    if (deviceId) {
      constraints.video.deviceId = { exact: deviceId };
      setDebugInfo(prev => prev + `\n使用 deviceId: ${deviceId}`);
    } else {
      constraints.video.facingMode = mode;
      setDebugInfo(prev => prev + `\n未找到 deviceId，降级使用 facingMode: ${mode}`);
    }
    getUserMediaCompat(constraints)
      .then(stream => {
        setDebugInfo(prevInfo => `${prevInfo}\n获取摄像头流成功，当前模式: ${mode}`);
        if (videoRef.current) {
          videoRef.current.srcObject = stream;
          videoRef.current.onloadedmetadata = () => {
            setDebugInfo(prevInfo => `${prevInfo}\n视频元数据加载成功`);
            videoRef.current.play().catch(err => {
              setErrorMsg('视频播放失败');
              setDebugInfo(prevInfo => `${prevInfo}\n视频播放错误: ${err.message}`);
            });
          };
        } else {
          setErrorMsg('未找到video元素');
          setDebugInfo(prevInfo => `${prevInfo}\n严重错误：video 元素不存在`);
          return;
        }
        streamRef.current = stream;
        // WebSocket 连接
        wsRef.current = new WebSocket(WS_SERVER);
        wsRef.current.onopen = () => {
          setDebugInfo(prevInfo => `${prevInfo}\nWebSocket 连接成功：${WS_SERVER}`);
          intervalRef.current = setInterval(() => {
            if (!canvasRef.current || !videoRef.current) {
              setErrorMsg('未找到canvas或video元素');
              setDebugInfo(prevInfo => `${prevInfo}\n推流时未找到canvas或video元素，已停止推流`);
              clearInterval(intervalRef.current);
              intervalRef.current = null;
              return;
            }
            try {
              const ctx = canvasRef.current.getContext('2d');
              const videoWidth = videoRef.current.videoWidth;
              const videoHeight = videoRef.current.videoHeight;

              // 修正：使用视频流的实际宽高绘制到 canvas
              canvasRef.current.width = videoWidth;
              canvasRef.current.height = videoHeight;
              ctx.drawImage(videoRef.current, 0, 0, videoWidth, videoHeight);

              canvasRef.current.toBlob(async blob => {
                if (blob && wsRef.current.readyState === 1) {
                  wsRef.current.send(blob); // 直接发送二进制图片
                }
              }, 'image/jpeg', 0.7);
            } catch (err) {
              setErrorMsg('图像捕获失败');
              setDebugInfo(prevInfo => `${prevInfo}\n图像捕获错误: ${err.message}`);
              clearInterval(intervalRef.current);
              intervalRef.current = null;
            }
          }, 200);
        };
        // 新增：接收后端消息
        wsRef.current.onmessage = (event) => {
          setDebugInfo(prev => prev + `\n[WebSocket] 收到消息: ${event.data}`);
          setWsMessage(event.data);
          // 只在首次收到后端消息时语音提示
          if (event.data && event.data.includes('连接成功')) {
            setDebugInfo(prev => prev + '\n[语音] 收到连接成功，调用 speakOnce');
            try {
              voiceHelper.current.speakOnce('连接成功');
              setDebugInfo(prev => prev + '\n[语音] speakOnce(连接成功) 已调用');
            } catch (e) {
              setDebugInfo(prev => prev + `\n[语音] speakOnce(连接成功) 调用失败: ${e.message}`);
            }
          }
        };
        wsRef.current.onerror = (e) => {
          setErrorMsg('WebSocket 连接失败');
          setDebugInfo(prevInfo => `${prevInfo}\nWebSocket 连接失败详情：\n服务器地址: ${WS_SERVER}\n错误码: ${e?.code || 'N/A'}\n错误信息: ${e?.message || 'Unknown error'}`);
        };
        wsRef.current.onclose = (e) => {
          setErrorMsg('WebSocket 连接已关闭');
          setDebugInfo(prevInfo => `${prevInfo}\nWebSocket 连接关闭详情：\n服务器地址: ${WS_SERVER}\n关闭码: ${e?.code || 'N/A'}\n关闭原因: ${e?.reason || 'Unknown reason'}`);
          if (intervalRef.current) {
            clearInterval(intervalRef.current);
            intervalRef.current = null;
          }
        };
      })
      .catch(err => {
        setErrorMsg('摄像头启动失败: ' + (err && err.message ? err.message : err));
        setDebugInfo(
          `摄像头启动错误详情：\n` +
          `错误名称: ${err?.name || ''}\n` +
          `错误消息: ${err?.message || ''}\n` +
          `错误堆栈: ${err?.stack || ''}\n` +
          `尝试模式: ${mode}`
        );
      });
  };

  // 切换摄像头
  const handleSwitchCamera = () => {
    voiceHelper.current.unlock(); // 新增：用户交互时解锁语音
    const nextMode = facingMode === 'environment' ? 'user' : 'environment';
    setDebugInfo(`准备切换摄像头，当前模式: ${facingMode}，下一个模式: ${nextMode}`);
    setFacingMode(nextMode);
  };

  // 拍照按钮事件
  const handleTakePhoto = () => {
    voiceHelper.current.unlock(); // 新增：用户交互时解锁语音
    if (wsRef.current && wsRef.current.readyState === 1) {
      setDebugInfo(prev => prev + '\n[前端] 发送拍照请求: { type: \'takePhoto\' }');
      wsRef.current.send(JSON.stringify({ type: 'takePhoto' }));
    } else {
      setDebugInfo(prev => prev + '\n[前端] WebSocket 未连接，无法发送拍照请求');
    }
  };

  // 切换调试信息折叠状态
  const toggleDebugPanel = () => {
    setIsDebugExpanded(prev => !prev);
  };

  useEffect(() => {
    // 页面加载时自动语音播报欢迎语
    try {
      voiceHelper.current.speak('欢迎使用多端综合学习平台摄像头功能测试');
      setDebugInfo(prev => prev + '\n[语音] 已自动播报欢迎语');
    } catch (e) {
      setDebugInfo(prev => prev + `\n[语音] 欢迎语播报失败: ${e.message}`);
    }
    // 切换时清理旧流/定时器/ws
    if (wsRef.current) wsRef.current.close();
    if (streamRef.current) streamRef.current.getTracks().forEach(track => track.stop());
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
    // 启动新摄像头
    setTimeout(() => startCameraAndWS(facingMode), 1500);
    return () => {
      if (wsRef.current) wsRef.current.close();
      if (streamRef.current) streamRef.current.getTracks().forEach(track => track.stop());
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
    };
    // eslint-disable-next-line
  }, [facingMode]);

  // 动态应用前摄像头镜像样式
  useEffect(() => {
    if (videoRef.current) {
      videoRef.current.style.transform = facingMode === 'user' ? 'scaleX(-1)' : 'none';
    }
  }, [facingMode]);

  return (
    <div style={{ textAlign: 'center', padding: 1, maxWidth: 480, margin: '0 auto' }}>
      <button onClick={handleSwitchCamera} style={{ marginBottom: 16, marginTop: 16 }}>
        切换{facingMode === 'environment' ? '前置' : '后置'}摄像头
      </button>
      {/* 先渲染预览，再渲染日志 */}
      <div style={{ marginBottom: 12 }}>
        <div style={{ position: 'relative', display: 'inline-block' }}>
          <video
            ref={videoRef}
            width={320}
            height={240}
            style={{ display: 'block' }}
          />
          <canvas ref={canvasRef} width={320} height={240} style={{ display: 'none' }} />
        </div>
        {/* 拍照按钮 */}
        <button onClick={handleTakePhoto} style={{ margin: '8px 0', background: '#1976d2', color: '#fff', border: 'none', borderRadius: 6, padding: '6px 18px', fontWeight: 500, cursor: 'pointer' }}>
          拍照
        </button>
        {/* 新增：显示后端返回的消息 */}
        {wsMessage && (
          <div style={{ margin: '8px auto', color: '#1976d2', fontWeight: 500, background: '#e3f2fd', borderRadius: 6, padding: 8, maxWidth: 320 }}>
            后端消息：{wsMessage}
          </div>
        )}
      </div>
      
      {/* 可折叠的调试信息面板 */}
      {(errorMsg || debugInfo) && (
        <div style={{ margin: '24px auto', maxWidth: 600 }}>
          <button
            onClick={toggleDebugPanel}
            style={{
              backgroundColor: '#f5f5f5',
              border: '1px solid #ddd',
              borderRadius: '6px 6px 0 0',
              padding: '8px 16px',
              cursor: 'pointer',
              fontSize: '14px',
              fontWeight: '500',
              color: '#333',
              width: '100%',
              textAlign: 'left',
              display: 'flex',
              justifyContent: 'space-between',
              alignItems: 'center'
            }}
          >
            <span>调试信息 {errorMsg && <span style={{ color: 'red', marginLeft: 8 }}>({errorMsg ? '有错误' : ''})</span>}</span>
            <span style={{ fontSize: '12px' }}>{isDebugExpanded ? '▼' : '▶'}</span>
          </button>
          
          {isDebugExpanded && (
            <div style={{
              color: errorMsg ? 'red' : '#666',
              padding: 12,
              backgroundColor: '#f9f9f9',
              border: '1px solid #ddd',
              borderTop: 'none',
              borderRadius: '0 0 8px 8px',
              textAlign: 'left',
              maxHeight: '400px',
              overflowY: 'auto'
            }}>
              {errorMsg && <div style={{ color: 'red', marginBottom: 8, fontWeight: 'bold' }}>错误: {errorMsg}</div>}
              {debugInfo && <pre style={{ fontSize: 12, whiteSpace: 'pre-wrap', margin: 0 }}>{debugInfo}</pre>}
            </div>
          )}
        </div>
      )}
    </div>
  );
};

export default AndroidCameraPage;

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
